/*
 * Copyright 2014 A.C.R. Development
 */

package acr.browser.lightning.view;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.net.MailTo;
import android.net.Uri;
import android.os.Build;
import android.os.Message;
import android.support.annotation.NonNull;
import android.text.InputType;
import android.text.method.PasswordTransformationMethod;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.EditText;
import android.widget.LinearLayout;

import com.tencent.smtt.export.external.interfaces.GeolocationPermissionsCallback;
import com.tencent.smtt.export.external.interfaces.HttpAuthHandler;
import com.tencent.smtt.export.external.interfaces.IX5WebChromeClient;
import com.tencent.smtt.export.external.interfaces.SslError;
import com.tencent.smtt.export.external.interfaces.SslErrorHandler;
import com.tencent.smtt.export.external.interfaces.WebResourceRequest;
import com.tencent.smtt.export.external.interfaces.WebResourceResponse;
import com.tencent.smtt.sdk.CookieManager;
import com.tencent.smtt.sdk.ValueCallback;
import com.tencent.smtt.sdk.WebChromeClient;
import com.tencent.smtt.sdk.WebSettings;
import com.tencent.smtt.sdk.WebView;
import com.tencent.smtt.sdk.WebViewClient;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URISyntaxException;

import acr.browser.lightning.R;
import acr.browser.lightning.app.AppConfig;
import acr.browser.lightning.constant.Constants;
import acr.browser.lightning.constant.StartPage;
import acr.browser.lightning.controller.BrowserController;
import acr.browser.lightning.download.LightningDownloadListener;
import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.utils.AdBlock;
import acr.browser.lightning.utils.IntentUtils;
import acr.browser.lightning.utils.Utils;
import acr.browser.lightning.view.x5.X5WebView;

public class LightningView {

    private final Title mTitle;
    private X5WebView mWebView;
    private BrowserController mBrowserController;
    private GestureDetector mGestureDetector;
    private final Activity mActivity;
    private WebSettings mSettings;
    private static String mHomepage;
    private static String mDefaultUserAgent;
    private static Bitmap mWebpageBitmap;
    private static PreferenceManager mPreferences;
    private final AdBlock mAdBlock;
    private IntentUtils mIntentUtils;
    private final Paint mPaint = new Paint();
    private boolean isForegroundTab;
    private boolean mTextReflow = false;
    private boolean mInvertPage = false;
    private static final int API = android.os.Build.VERSION.SDK_INT;
    private static final int SCROLL_UP_THRESHOLD = Utils.convertDpToPixels(10);
    private static final int SCROLL_DOWN_THRESHOLD = Utils.convertDpToPixels(100);
    private static final float[] mNegativeColorArray = {-1.0f, 0, 0, 0, 255, // red
            0, -1.0f, 0, 0, 255, // green
            0, 0, -1.0f, 0, 255, // blue
            0, 0, 0, 1.0f, 0 // alpha
    };

    @SuppressWarnings("deprecation")
    @SuppressLint("NewApi")
    public LightningView(Activity activity, String url, boolean darkTheme) {

        mActivity = activity;
        mWebView = new X5WebView((Context) activity);
        mTitle = new Title(activity, darkTheme);
        mAdBlock = AdBlock.getInstance(activity.getApplicationContext());

        mWebpageBitmap = Utils.getWebpageBitmap(activity.getResources(), darkTheme);

        try {
            mBrowserController = (BrowserController) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity + " must implement BrowserController");
        }
        mIntentUtils = new IntentUtils(mBrowserController);
        mWebView.setDrawingCacheBackgroundColor(0x00000000);
        mWebView.setFocusableInTouchMode(true);
        mWebView.setFocusable(true);
        mWebView.setAnimationCacheEnabled(false);
        mWebView.setDrawingCacheEnabled(false);
        mWebView.setWillNotCacheDrawing(true);
        mWebView.setAlwaysDrawnWithCacheEnabled(false);
        mWebView.setBackgroundColor(activity.getResources().getColor(android.R.color.white));

        if (API > 15) {
            mWebView.setBackground(null);
            mWebView.getRootView().setBackground(null);
        } else if (mWebView.getRootView() != null) {
            mWebView.getRootView().setBackgroundDrawable(null);
        }
        mWebView.setScrollbarFadingEnabled(true);
        mWebView.setSaveEnabled(true);
        mWebView.setWebChromeClient(new LightningChromeClient(activity));
        mWebView.setWebViewClient(new LightningWebClient(activity));
        mWebView.setDownloadListener(new LightningDownloadListener(activity));
        mGestureDetector = new GestureDetector(activity, new CustomGestureListener());
        mWebView.setOnTouchListener(new TouchListener());
        mDefaultUserAgent = mWebView.getSettings().getUserAgentString();
        mSettings = mWebView.getSettings();
        initializeSettings(mWebView.getSettings(), activity);
        initializePreferences(activity);

        if (url != null) {
            if (!url.trim().isEmpty()) {
                mWebView.loadUrl(url);
            } else {
                // don't load anything, the user is looking for a blank tab
            }
        } else {
            if (mHomepage.startsWith("about:home")) {
                mWebView.loadUrl(getHomepage());
            } else if (mHomepage.startsWith("about:bookmarks")) {
                mBrowserController.openBookmarkPage(mWebView);
            } else {
                mWebView.loadUrl(mHomepage);
            }
        }
    }

    public String getHomepage() {
        StringBuilder homepageBuilder = new StringBuilder();
        homepageBuilder.append(StartPage.HEAD);
        String icon;
        String searchUrl;
        switch (mPreferences.getSearchChoice()) {
            case 0:
                // CUSTOM SEARCH
                icon = "file:///android_asset/lightning.png";
                searchUrl = mPreferences.getSearchUrl();
                break;
            case 1:
                // GOOGLE_SEARCH;
                icon = "file:///android_asset/google.png";
                // "https://www.google.com/images/srpr/logo11w.png";
                searchUrl = Constants.GOOGLE_SEARCH;
                break;
            case 2:
                // ANDROID SEARCH;
                icon = "file:///android_asset/ask.png";
                searchUrl = Constants.ASK_SEARCH;
                break;
            case 3:
                // BING_SEARCH;
                icon = "file:///android_asset/bing.png";
                // "http://upload.wikimedia.org/wikipedia/commons/thumb/b/b1/Bing_logo_%282013%29.svg/500px-Bing_logo_%282013%29.svg.png";
                searchUrl = Constants.BING_SEARCH;
                break;
            case 4:
                // YAHOO_SEARCH;
                icon = "file:///android_asset/yahoo.png";
                // "http://upload.wikimedia.org/wikipedia/commons/thumb/2/24/Yahoo%21_logo.svg/799px-Yahoo%21_logo.svg.png";
                searchUrl = Constants.YAHOO_SEARCH;
                break;
            case 5:
                // STARTPAGE_SEARCH;
                icon = "file:///android_asset/startpage.png";
                // "https://startpage.com/graphics/startp_logo.gif";
                searchUrl = Constants.STARTPAGE_SEARCH;
                break;
            case 6:
                // STARTPAGE_MOBILE
                icon = "file:///android_asset/startpage.png";
                // "https://startpage.com/graphics/startp_logo.gif";
                searchUrl = Constants.STARTPAGE_MOBILE_SEARCH;
                break;
            case 7:
                // DUCK_SEARCH;
                icon = "file:///android_asset/duckduckgo.png";
                // "https://duckduckgo.com/assets/logo_homepage.normal.v101.png";
                searchUrl = Constants.DUCK_SEARCH;
                break;
            case 8:
                // DUCK_LITE_SEARCH;
                icon = "file:///android_asset/duckduckgo.png";
                // "https://duckduckgo.com/assets/logo_homepage.normal.v101.png";
                searchUrl = Constants.DUCK_LITE_SEARCH;
                break;
            case 9:
                // BAIDU_SEARCH;
                icon = "file:///android_asset/baidu.png";
                // "http://www.baidu.com/img/bdlogo.gif";
                searchUrl = Constants.BAIDU_SEARCH;
                break;
            case 10:
                // YANDEX_SEARCH;
                icon = "file:///android_asset/yandex.png";
                // "http://upload.wikimedia.org/wikipedia/commons/thumb/9/91/Yandex.svg/600px-Yandex.svg.png";
                searchUrl = Constants.YANDEX_SEARCH;
                break;
            default:
                // DEFAULT GOOGLE_SEARCH;
                icon = "file:///android_asset/google.png";
                searchUrl = Constants.GOOGLE_SEARCH;
                break;

        }

        homepageBuilder.append(icon);
        homepageBuilder.append(StartPage.MIDDLE);
        homepageBuilder.append(searchUrl);
        homepageBuilder.append(StartPage.END);

        File homepage = new File(mActivity.getFilesDir(), "homepage.html");
        try {
            FileWriter hWriter = new FileWriter(homepage, false);
            hWriter.write(homepageBuilder.toString());
            hWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return Constants.FILE + homepage;
    }

    @SuppressWarnings("deprecation")
    @SuppressLint({"NewApi", "SetJavaScriptEnabled"})
    public synchronized void initializePreferences(Context context) {
        mPreferences = PreferenceManager.getInstance();
        mHomepage = mPreferences.getHomepage();
        mAdBlock.updatePreference();
        if (mSettings == null && mWebView != null) {
            mSettings = mWebView.getSettings();
        } else if (mSettings == null) {
            return;
        }

        setColorMode(mPreferences.getRenderingMode());

        if (!mBrowserController.isIncognito()) {
            mSettings.setGeolocationEnabled(mPreferences.getLocationEnabled());
        } else {
            mSettings.setGeolocationEnabled(false);
        }
        if (API < 19) {
            switch (mPreferences.getFlashSupport()) {
                case 0:
                    mSettings.setPluginState(WebSettings.PluginState.OFF);
                    break;
                case 1:
                    mSettings.setPluginState(WebSettings.PluginState.ON_DEMAND);
                    break;
                case 2:
                    mSettings.setPluginState(WebSettings.PluginState.ON);
                    break;
                default:
                    break;
            }
        }

        switch (mPreferences.getUserAgentChoice()) {
            case 1:
                if (API > 16) {
                    mSettings.setUserAgentString(WebSettings.getDefaultUserAgent(context));
                } else {
                    mSettings.setUserAgentString(mDefaultUserAgent);
                }
                break;
            case 2:
                mSettings.setUserAgentString(Constants.DESKTOP_USER_AGENT);
                break;
            case 3:
                mSettings.setUserAgentString(Constants.MOBILE_USER_AGENT);
                break;
            case 4:
                mSettings.setUserAgentString(mPreferences.getUserAgentString(mDefaultUserAgent));
                break;
        }

        if (mPreferences.getSavePasswordsEnabled() && !mBrowserController.isIncognito()) {
            if (API < 18) {
                mSettings.setSavePassword(true);
            }
            mSettings.setSaveFormData(true);
        } else {
            if (API < 18) {
                mSettings.setSavePassword(false);
            }
            mSettings.setSaveFormData(false);
        }

        if (mPreferences.getJavaScriptEnabled()) {
            mSettings.setJavaScriptEnabled(true);
            mSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        }

        if (mPreferences.getTextReflowEnabled()) {
            mTextReflow = true;
            mSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
            if (API >= android.os.Build.VERSION_CODES.KITKAT) {
                try {
//                    mSettings.setLayoutAlgorithm(LayoutAlgorithm.TEXT_AUTOSIZING);
                } catch (Exception e) {
                    // This shouldn't be necessary, but there are a number
                    // of KitKat devices that crash trying to set this
                    Log.e(Constants.TAG, "Problem setting LayoutAlgorithm to TEXT_AUTOSIZING");
                }
            }
        } else {
            mTextReflow = false;
            mSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);
        }

        mSettings.setBlockNetworkImage(mPreferences.getBlockImagesEnabled());
        mSettings.setSupportMultipleWindows(mPreferences.getPopupsEnabled());
        mSettings.setUseWideViewPort(mPreferences.getUseWideViewportEnabled());
        mSettings.setLoadWithOverviewMode(mPreferences.getOverviewModeEnabled());
        switch (mPreferences.getTextSize()) {
            case 1:
                mSettings.setTextZoom(200);
                break;
            case 2:
                mSettings.setTextZoom(150);
                break;
            case 3:
                mSettings.setTextZoom(100);
                break;
            case 4:
                mSettings.setTextZoom(75);
                break;
            case 5:
                mSettings.setTextZoom(50);
                break;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            CookieManager.getInstance().setAcceptThirdPartyCookies(
                    !mPreferences.getBlockThirdPartyCookiesEnabled());
//            CookieManager.getInstance().setAcceptThirdPartyCookies(mWebView,
//                    !mPreferences.getBlockThirdPartyCookiesEnabled());
        }
    }

    @SuppressWarnings("deprecation")
    @SuppressLint({"SetJavaScriptEnabled", "NewApi"})
    public void initializeSettings(WebSettings settings, Context context) {
//        if(Build.VERSION.SDK_INT >= 19) {
//            settings.setLoadsImagesAutomatically(true);
//        } else {
//            settings.setLoadsImagesAutomatically(false);
//        }

        //提高渲染的优先级
//        settings.setRenderPriority(WebSettings.RenderPriority.HIGH);

        if (API < 18) {
            settings.setAppCacheMaxSize(Long.MAX_VALUE);
        }
        if (API < 17) {
            settings.setEnableSmoothTransition(true);
        }
        if (API > 16) {
            settings.setMediaPlaybackRequiresUserGesture(true);
        }
        if (API >= Build.VERSION_CODES.LOLLIPOP && !mBrowserController.isIncognito()) {
            //TODO
//            settings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
        } else if (API >= Build.VERSION_CODES.LOLLIPOP) {
            // We're in Incognito mode, reject
            //TODO
//            settings.setMixedContentMode(WebSettings.MIXED_CONTENT_NEVER_ALLOW);
        }
        settings.setDomStorageEnabled(true);
        settings.setAppCacheEnabled(true);

        //: : 总结：根据以上两种模式，建议缓存策略为，判断是否有网络，有的话，使用LOAD_DEFAULT，无网络时，使用LOAD_CACHE_ELSE_NETWORK。
        settings.setCacheMode(AppConfig.isNetConnected ? WebSettings.LOAD_DEFAULT : WebSettings.LOAD_CACHE_ELSE_NETWORK);
        settings.setDatabaseEnabled(true);
        settings.setSupportZoom(true);
        settings.setBuiltInZoomControls(true);
        settings.setDisplayZoomControls(false);
        settings.setAllowContentAccess(true);
        settings.setAllowFileAccess(true);
        settings.setDefaultTextEncodingName("utf-8");
        if (API > 16) {
            settings.setAllowFileAccessFromFileURLs(false);
            settings.setAllowUniversalAccessFromFileURLs(false);
        }

        settings.setAppCachePath(context.getDir("appcache", 0).getPath());
        settings.setGeolocationDatabasePath(context.getDir("geolocation", 0).getPath());
        if (API < Build.VERSION_CODES.KITKAT) {
            settings.setDatabasePath(context.getDir("databases", 0).getPath());
        }
    }

    public boolean isShown() {
        return mWebView != null && mWebView.isShown();
    }

    public synchronized void onPause() {
        if (mWebView != null) {
            mWebView.onPause();
        }
    }

    public synchronized void onResume() {
        if (mWebView != null) {
            mWebView.onResume();
        }
    }

    public void setForegroundTab(boolean isForeground) {
        isForegroundTab = isForeground;
        mBrowserController.update();
    }

    public boolean isForegroundTab() {
        return isForegroundTab;
    }

    public int getProgress() {
        if (mWebView != null) {
            return mWebView.getProgress();
        } else {
            return 100;
        }
    }

    public synchronized void stopLoading() {
        if (mWebView != null) {
            mWebView.stopLoading();
        }
    }

    public void setHardwareRendering() {
        mWebView.setLayerType(View.LAYER_TYPE_HARDWARE, mPaint);
    }

    public void setNormalRendering() {
        mWebView.setLayerType(View.LAYER_TYPE_NONE, null);
    }

    public void setSoftwareRendering() {
        mWebView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }

    public void setColorMode(int mode) {
        mInvertPage = false;
        switch (mode) {
            case 0:
                mPaint.setColorFilter(null);
                // setSoftwareRendering(); // Some devices get segfaults
                // in the WebView with Hardware Acceleration enabled,
                // the only fix is to disable hardware rendering
                setNormalRendering();
                mInvertPage = false;
                break;
            case 1:
                ColorMatrixColorFilter filterInvert = new ColorMatrixColorFilter(
                        mNegativeColorArray);
                mPaint.setColorFilter(filterInvert);
                setHardwareRendering();

                mInvertPage = true;
                break;
            case 2:
                ColorMatrix cm = new ColorMatrix();
                cm.setSaturation(0);
                ColorMatrixColorFilter filterGray = new ColorMatrixColorFilter(cm);
                mPaint.setColorFilter(filterGray);
                setHardwareRendering();
                break;
            case 3:
                ColorMatrix matrix = new ColorMatrix();
                matrix.set(mNegativeColorArray);
                ColorMatrix matrixGray = new ColorMatrix();
                matrixGray.setSaturation(0);
                ColorMatrix concat = new ColorMatrix();
                concat.setConcat(matrix, matrixGray);
                ColorMatrixColorFilter filterInvertGray = new ColorMatrixColorFilter(concat);
                mPaint.setColorFilter(filterInvertGray);
                setHardwareRendering();

                mInvertPage = true;
                break;

        }

    }

    public synchronized void pauseTimers() {
        if (mWebView != null) {
            mWebView.pauseTimers();
        }
    }

    public synchronized void resumeTimers() {
        if (mWebView != null) {
            mWebView.resumeTimers();
        }
    }

    public void requestFocus() {
        if (mWebView != null && !mWebView.hasFocus()) {
            mWebView.requestFocus();
        }
    }

    public void setVisibility(int visible) {
        if (mWebView != null) {
            mWebView.setVisibility(visible);
        }
    }

    public void clearCache(boolean disk) {
        if (mWebView != null) {
            mWebView.clearCache(disk);
        }
    }

    public synchronized void reload() {
        // Check if configured proxy is available
        if (!mBrowserController.isProxyReady()) {
            // User has been notified
            return;
        }

        if (mWebView != null) {
            mWebView.reload();
        }
    }

    private void cacheFavicon(Bitmap icon) {
        String hash = String.valueOf(Utils.getDomainName(getUrl()).hashCode());
        Log.d(Constants.TAG, "Caching icon for " + Utils.getDomainName(getUrl()));
        File image = new File(mActivity.getCacheDir(), hash + ".png");
        try {
            FileOutputStream fos = new FileOutputStream(image);
            icon.compress(Bitmap.CompressFormat.PNG, 100, fos);
            fos.flush();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @SuppressWarnings("deprecation")
    @SuppressLint("NewApi")
    public synchronized void find(String text) {
        if (mWebView != null) {
            if (API > 16) {
                mWebView.findAllAsync(text);
            } else {
                mWebView.findAll(text);
            }
        }
    }

    public Activity getActivity() {
        return mActivity;
    }

    public synchronized void onDestroy() {
        if (mWebView != null) {
            mWebView.stopLoading();
            mWebView.onPause();
            mWebView.clearHistory();
            mWebView.setVisibility(View.GONE);
            mWebView.removeAllViews();
            mWebView.destroyDrawingCache();
            // mWebView.destroy(); //this is causing the segfault
            mWebView = null;
        }
    }

    public synchronized void goBack() {
        if (mWebView != null) {
            mWebView.goBack();
        }
    }

    public String getUserAgent() {
        if (mWebView != null) {
            return mWebView.getSettings().getUserAgentString();
        } else {
            return "";
        }
    }

    public synchronized void goForward() {
        if (mWebView != null) {
            mWebView.goForward();
        }
    }

    public boolean canGoBack() {
        return mWebView != null && mWebView.canGoBack();
    }

    public boolean canGoForward() {
        return mWebView != null && mWebView.canGoForward();
    }

    public X5WebView getWebView() {
        return mWebView;
    }

    public Bitmap getFavicon() {
        return mTitle.getFavicon();
    }

    public synchronized void loadUrl(String url) {
        // Check if configured proxy is available
        if (!mBrowserController.isProxyReady()) {
            // User has been notified
            return;
        }

        if (mWebView != null) {
            mWebView.loadUrl(url);
        }
    }

    public synchronized void invalidate() {
        if (mWebView != null) {
            mWebView.invalidate();
        }
    }

    public String getTitle() {
        return mTitle.getTitle();
    }

    public String getUrl() {
        if (mWebView != null) {
            return mWebView.getUrl();
        } else {
            return "";
        }
    }

    public class LightningWebClient extends WebViewClient {

        final Context mActivity;

        LightningWebClient(Context context) {
            mActivity = context;
        }

        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
            if (mAdBlock.isAd(request.getUrl().getHost())) {
                ByteArrayInputStream EMPTY = new ByteArrayInputStream("".getBytes());
                return new WebResourceResponse("text/plain", "utf-8", EMPTY);
            }

            return super.shouldInterceptRequest(view, request);
        }

//        public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
//            Log.i(TAG, "shouldInterceptRequest url=" + url + ";threadInfo" + Thread.currentThread());
//            WebResourceResponse response = null;
//            if (url.contains("avatar.php?")) {
//                Bitmap bitmap = ImageLoader.getInstance().loadImageSync(url);
//                if (bitmap != null) {
//                    InputStream in = IOUtils.bitmap2InputStream(bitmap, 100);
//                    response = new WebResourceResponse("image/png", "UTF-8", in);
//                }
//            }
//            return response;
//        }
//
//        WebResourceResponse shouldInterceptRequest(WebView view, String url) {
//            Log.i(TAG, "shouldInterceptRequest url=" + url + ";threadInfo" + Thread.currentThread());
//            WebResourceResponse response = null;
//            if (url.contains("avatar.php?")) {
//                try {
//                    final PipedOutputStream out = new PipedOutputStream();
//                    PipedInputStream in = new PipedInputStream(out);
//                    ImageLoader.getInstance().loadImage(url, new ImageLoadingListener() {
//                        @Override
//                        public void onLoadingStarted(String s, View view) {
//                        }
//
//                        @Override
//                        public void onLoadingFailed(String s, View view, FailReason failReason) {
//                        }
//
//                        @Override
//                        public void onLoadingCancelled(String s, View view) {
//                        }
//
//                        @Override
//                        public void onLoadingComplete(String s, View view, Bitmap bitmap) {
//                            if (bitmap != null) {
//                                try {
//                                    out.write(IOUtils.Bitmap2Bytes(bitmap));
//                                    out.close();
//                                } catch (Exception e) {
//                                    e.printStackTrace();
//                                }
//                            }
//                        }
//                    });
//                    response = new WebResourceResponse("image/png", "UTF-8", in);
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
//            }
//            return response;
//        }

        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
            if (mAdBlock.isAd(url)) {
                ByteArrayInputStream EMPTY = new ByteArrayInputStream("".getBytes());
                return new WebResourceResponse("text/plain", "utf-8", EMPTY);
            }
//             else if (url.contains(".png") || url.contains(".jpg") || url.contains(".jpeg ") || url.contains(".gif") || url.contains(".png") || url.contains(".bmp")) {
//                final PipedOutputStream out = new PipedOutputStream();
//                PipedInputStream in = null;
//                try {
//                    in = new PipedInputStream(out);
//                    ImageLoader.getInstance().loadImage("http://img.sc115.com/uploads2/sc/png/dw_26/Icon_10.png", new ImageLoadingListener() {
//                        @Override
//                        public void onLoadingStarted(String s, View view) {
//                        }
//
//                        @Override
//                        public void onLoadingFailed(String s, View view, FailReason failReason) {
//                        }
//
//                        @Override
//                        public void onLoadingCancelled(String s, View view) {
//                        }
//
//                        @Override
//                        public void onLoadingComplete(String s, View view, Bitmap bitmap) {
//                            if (bitmap != null) {
//                                try {
//                                    out.write(Bitmap2Bytes(bitmap));
//                                    out.close();
//                                } catch (Exception e) {
//                                    e.printStackTrace();
//                                }
//                            }
//                        }
//                    });
//                    Log.e("ww","WebResourceResponse"+url);
//                    WebResourceResponse response = new WebResourceResponse("image/png", "UTF-8", in);
//                    return response;
//
////                    InputStream localCopy = mActivity.getAssets().open("baidu.png");
////                    WebResourceResponse response = new WebResourceResponse("image/png", "UTF-8", localCopy);
////                    return response;
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
//            }
            return null;
        }

        public byte[] Bitmap2Bytes(Bitmap bm) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
            return baos.toByteArray();
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            if (view.isShown()) {
                mBrowserController.updateUrl(url, true);
                view.postInvalidate();
            }
            if (view.getTitle() == null || view.getTitle().isEmpty()) {
                mTitle.setTitle(mActivity.getString(R.string.untitled));
            } else {
                mTitle.setTitle(view.getTitle());
            }
            if (API >= android.os.Build.VERSION_CODES.KITKAT && mInvertPage) {
                view.evaluateJavascript(Constants.JAVASCRIPT_INVERT_PAGE, null);
            }
//            if(!mWebView.getSettings().getLoadsImagesAutomatically()) {
//                mWebView.getSettings().setLoadsImagesAutomatically(true);
//            }
            Log.e("www", "开启硬件加速=" + getWebView().isHardwareAccelerated());
            mBrowserController.update();
            mBrowserController.onPageFinished();
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            if (isShown()) {
                mBrowserController.updateUrl(url, false);
                mBrowserController.showActionBar();
            }
//            mWebView.getSettings().setLoadsImagesAutomatically(false);
            mTitle.setFavicon(mWebpageBitmap);
            mBrowserController.update();
            mBrowserController.onPageStarted();
        }

        @Override
        public void onReceivedHttpAuthRequest(final WebView view, @NonNull final HttpAuthHandler handler,
                                              final String host, final String realm) {

            AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
            final EditText name = new EditText(mActivity);
            final EditText password = new EditText(mActivity);
            LinearLayout passLayout = new LinearLayout(mActivity);
            passLayout.setOrientation(LinearLayout.VERTICAL);

            passLayout.addView(name);
            passLayout.addView(password);

            name.setHint(mActivity.getString(R.string.hint_username));
            name.setSingleLine();
            password.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
            password.setSingleLine();
            password.setTransformationMethod(new PasswordTransformationMethod());
            password.setHint(mActivity.getString(R.string.hint_password));
            builder.setTitle(mActivity.getString(R.string.title_sign_in));
            builder.setView(passLayout);
            builder.setCancelable(true)
                    .setPositiveButton(mActivity.getString(R.string.title_sign_in),
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int id) {
                                    String user = name.getText().toString();
                                    String pass = password.getText().toString();
                                    handler.proceed(user.trim(), pass.trim());
                                    Log.d(Constants.TAG, "Request Login");

                                }
                            })
                    .setNegativeButton(mActivity.getString(R.string.action_cancel),
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int id) {
                                    handler.cancel();

                                }
                            });
            AlertDialog alert = builder.create();
            alert.show();

        }

        private boolean mIsRunning = false;
        private float mZoomScale = 0.0f;

        @Override
        public void onScaleChanged(final WebView view, final float oldScale, final float newScale) {
            if (view.isShown() && mTextReflow && API >= android.os.Build.VERSION_CODES.KITKAT) {
                if (mIsRunning)
                    return;
                if (Math.abs(mZoomScale - newScale) > 0.01f) {
                    mIsRunning = view.postDelayed(new Runnable() {

                        @Override
                        public void run() {
                            mZoomScale = newScale;
                            view.evaluateJavascript(Constants.JAVASCRIPT_TEXT_REFLOW, null);
                            mIsRunning = false;
                        }

                    }, 100);
                }

            }
        }


        @Override
        public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
//            var2.cancel();
            AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
            builder.setTitle(mActivity.getString(R.string.title_warning));
            builder.setMessage(mActivity.getString(R.string.message_untrusted_certificate))
                    .setCancelable(true)
                    .setPositiveButton(mActivity.getString(R.string.action_yes),
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int id) {
                                    handler.proceed();
                                }
                            })
                    .setNegativeButton(mActivity.getString(R.string.action_no),
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int id) {
                                    handler.cancel();
                                }
                            });
            AlertDialog alert = builder.create();
            if (error.getPrimaryError() == android.net.http.SslError.SSL_UNTRUSTED) {
                alert.show();
            } else {
                handler.proceed();
            }
        }


        @Override
        public void onFormResubmission(WebView view, @NonNull final Message dontResend, final Message resend) {
            AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
            builder.setTitle(mActivity.getString(R.string.title_form_resubmission));
            builder.setMessage(mActivity.getString(R.string.message_form_resubmission))
                    .setCancelable(true)
                    .setPositiveButton(mActivity.getString(R.string.action_yes),
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int id) {

                                    resend.sendToTarget();
                                }
                            })
                    .setNegativeButton(mActivity.getString(R.string.action_no),
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int id) {

                                    dontResend.sendToTarget();
                                }
                            });
            AlertDialog alert = builder.create();
            alert.show();
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            Log.e("www", "shouldOverrideUrlLoading=" + url);
            Log.e("www", "shouldOverrideUrlLoading" + view.getHitTestResult());
            // Check if configured proxy is available
//            if (url.startsWith("http") && !url.contains("pdf")) {
//                view.loadUrl(url);
//                return true;
//            } else {
//                return true;
//            }


            if (!mBrowserController.isProxyReady()) {
                // User has been notified
                return true;
            }

            if (mBrowserController.isIncognito()) {
                return super.shouldOverrideUrlLoading(view, url);
            }
            if (url.startsWith("about:")) {
                return super.shouldOverrideUrlLoading(view, url);
            }
            if (url.contains("mailto:")) {
                MailTo mailTo = MailTo.parse(url);
                Intent i = Utils.newEmailIntent(mActivity, mailTo.getTo(), mailTo.getSubject(),
                        mailTo.getBody(), mailTo.getCc());
                mActivity.startActivity(i);
                view.reload();
                return true;
            } else if (url.startsWith("intent://")) {
                Intent intent;
                try {
                    intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
                } catch (URISyntaxException ex) {
                    return false;
                }
                if (intent != null) {
                    try {
                        mActivity.startActivity(intent);
                    } catch (ActivityNotFoundException e) {
                        Log.e(Constants.TAG, "ActivityNotFoundException");
                    }
                    return true;
                }
            }
            return mIntentUtils.startActivityForUrl(mWebView, url);
        }
    }

    public class LightningChromeClient extends com.tencent.smtt.sdk.WebChromeClient {

        final Context mActivity;

        LightningChromeClient(Context context) {
            mActivity = context;
        }

        @Override
        public void onProgressChanged(WebView view, int newProgress) {
            if (isShown()) {
                mBrowserController.updateProgress(newProgress);
                mBrowserController.onProgressChanged(newProgress);
            }
        }

        @Override
        public void onReceivedIcon(WebView view, Bitmap icon) {
            mTitle.setFavicon(icon);
            mBrowserController.update();
            cacheFavicon(icon);
        }

        @Override
        public void onReceivedTitle(WebView view, String title) {
            if (!title.isEmpty()) {
                mTitle.setTitle(title);
            } else {
                mTitle.setTitle(mActivity.getString(R.string.untitled));
            }
            mBrowserController.update();
            mBrowserController.updateHistory(title, view.getUrl());
        }


        @Override
        public void onGeolocationPermissionsShowPrompt(final String origin, final GeolocationPermissionsCallback callback) {
            final boolean remember = true;
            AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
            builder.setTitle(mActivity.getString(R.string.location));
            String org;
            if (origin.length() > 50) {
                org = origin.subSequence(0, 50) + "...";
            } else {
                org = origin;
            }
            builder.setMessage(org + mActivity.getString(R.string.message_location))
                    .setCancelable(true)
                    .setPositiveButton(mActivity.getString(R.string.action_allow),
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int id) {
                                    callback.invoke(origin, true, remember);
                                }
                            })
                    .setNegativeButton(mActivity.getString(R.string.action_dont_allow),
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int id) {
                                    callback.invoke(origin, false, remember);
                                }
                            });
            AlertDialog alert = builder.create();
            alert.show();
        }

        @Override
        public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture,
                                      Message resultMsg) {
            mBrowserController.onCreateWindow(isUserGesture, resultMsg);
            return true;
        }

        @Override
        public void onCloseWindow(WebView window) {
            // TODO Auto-generated method stub
            super.onCloseWindow(window);
        }

        public void openFileChooser(ValueCallback<Uri> uploadMsg) {
            mBrowserController.openFileChooser(uploadMsg);
        }

        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
            mBrowserController.openFileChooser(uploadMsg);
        }

        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
            mBrowserController.openFileChooser(uploadMsg);
        }

        public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,
                                         android.webkit.WebChromeClient.FileChooserParams fileChooserParams) {
            mBrowserController.showFileChooser(filePathCallback);
            return true;
        }

        @Override
        public Bitmap getDefaultVideoPoster() {
            return mBrowserController.getDefaultVideoPoster();
        }

        @Override
        public View getVideoLoadingProgressView() {
            return mBrowserController.getVideoLoadingProgressView();
        }

        @Override
        public void onHideCustomView() {
            mBrowserController.onHideCustomView();
            super.onHideCustomView();
        }

        @Override
        public void onShowCustomView(View view, IX5WebChromeClient.CustomViewCallback callback) {
            // While these lines might look like they work, in practice,
            // Full-screen videos won't work correctly. I may test this out some
            // more
            // if (view instanceof FrameLayout) {
            // FrameLayout frame = (FrameLayout) view;
            // if (frame.getFocusedChild() instanceof VideoView) {
            // VideoView video = (VideoView) frame.getFocusedChild();
            // video.stopPlayback();
            // frame.removeView(video);
            // video.setVisibility(View.GONE);
            // }
            // } else {
            Activity activity = mBrowserController.getActivity();
            mBrowserController.onShowCustomView(view, activity.getRequestedOrientation(), callback);

            // }

            super.onShowCustomView(view, callback);
        }

        @Override
        @Deprecated
        public void onShowCustomView(View view, int requestedOrientation,
                                     IX5WebChromeClient.CustomViewCallback callback) {
            // While these lines might look like they work, in practice,
            // Full-screen videos won't work correctly. I may test this out some
            // more
            // if (view instanceof FrameLayout) {
            // FrameLayout frame = (FrameLayout) view;
            // if (frame.getFocusedChild() instanceof VideoView) {
            // VideoView video = (VideoView) frame.getFocusedChild();
            // video.stopPlayback();
            // frame.removeView(video);
            // video.setVisibility(View.GONE);
            // }
            // } else {
            mBrowserController.onShowCustomView(view, requestedOrientation, callback);

            // }

            super.onShowCustomView(view, requestedOrientation, callback);
        }
    }

    public class Title {

        private Bitmap mFavicon;
        private String mTitle;
        private final Bitmap mDefaultIcon;

        public Title(Context context, boolean darkTheme) {
            mDefaultIcon = Utils.getWebpageBitmap(context.getResources(), darkTheme);
            mFavicon = mDefaultIcon;
            mTitle = mActivity.getString(R.string.action_new_tab);
        }

        public void setFavicon(Bitmap favicon) {
            if (favicon == null) {
                mFavicon = mDefaultIcon;
            } else {
                mFavicon = Utils.padFavicon(favicon);
            }
        }

        public void setTitle(String title) {
            if (title == null) {
                mTitle = "";
            } else {
                mTitle = title;
            }
        }

        public void setTitleAndFavicon(String title, Bitmap favicon) {
            mTitle = title;

            if (favicon == null) {
                mFavicon = mDefaultIcon;
            } else {
                mFavicon = Utils.padFavicon(favicon);
            }
        }

        public String getTitle() {
            return mTitle;
        }

        public Bitmap getFavicon() {
            return mFavicon;
        }

    }

    private class TouchListener implements OnTouchListener {

        float mLocation;
        float mY;
        int mAction;

        @SuppressLint("ClickableViewAccessibility")
        @Override
        public boolean onTouch(View view, MotionEvent arg1) {
            if (view != null && !view.hasFocus()) {
                view.requestFocus();
            }
            mAction = arg1.getAction();
            mY = arg1.getY();
            if (mAction == MotionEvent.ACTION_DOWN) {
                mLocation = mY;
            } else if (mAction == MotionEvent.ACTION_UP) {
                if ((mY - mLocation) > SCROLL_DOWN_THRESHOLD) {
                    if (mWebView.getScrollY() != 0) {
                        mBrowserController.showActionBar();
                    } else {
                        mBrowserController.toggleActionBar();
                    }
                } else if ((mY - mLocation) < -SCROLL_UP_THRESHOLD) {
                    mBrowserController.hideActionBar();
                }
                mLocation = 0;
            }
            mGestureDetector.onTouchEvent(arg1);
            return false;
        }
    }

    private class CustomGestureListener extends SimpleOnGestureListener {

        /**
         * Without this, onLongPress is not called when user is zooming using
         * two fingers, but is when using only one.
         * <p/>
         * The required behaviour is to not trigger this when the user is
         * zooming, it shouldn't matter how much fingers the user's using.
         */
        private boolean mCanTriggerLongPress = true;

        @Override
        public void onLongPress(MotionEvent e) {
            if (mCanTriggerLongPress)
                mBrowserController.onLongPress();
        }

        /**
         * Is called when the user is swiping after the doubletap, which in our
         * case means that he is zooming.
         */
        @Override
        public boolean onDoubleTapEvent(MotionEvent e) {
            mCanTriggerLongPress = false;
            return false;
        }

        /**
         * Is called when something is starting being pressed, always before
         * onLongPress.
         */
        @Override
        public void onShowPress(MotionEvent e) {
            mCanTriggerLongPress = true;
        }
    }
}
